home *** CD-ROM | disk | FTP | other *** search
/ An Introduction to Progr…l Basic 6.0 (4th Edition) / An Introduction to Programming using Visual Basic 6.0.iso / COMMON / TOOLS / VB / CABINETS / MSDAO350.CAB / icontrols / Data / DataProvider.class (.txt) next >
Encoding:
Java Class File  |  1998-01-08  |  21.0 KB  |  1,125 lines

  1. package icontrols.Data;
  2.  
  3. import com.ms.ado.AdoException;
  4. import com.ms.ado.Field;
  5. import com.ms.ado.Recordset;
  6. import com.ms.ado.RecordsetEvent;
  7. import com.ms.ado.RecordsetEventHandler;
  8. import com.ms.com.Variant;
  9. import com.ms.wd.app.Message;
  10. import com.ms.wd.core.CancelEvent;
  11. import com.ms.wd.util.Debug;
  12. import com.ms.wd.win32.Windows;
  13.  
  14. public class DataProvider {
  15.    private static final float INVALID_RATIO = -23.23F;
  16.    private static final int WM_DELAY_ACTION = 2476;
  17.    private static final int DELAY_FIND_NEW_CURRENT_ROW = 1;
  18.    private float m_cacheStartRatio = -23.23F;
  19.    private float m_cacheRowRatioSize = -23.23F;
  20.    private Object[] m_bookmarkCache = new Object[30];
  21.    private int m_pageSize = 10;
  22.    private int m_cacheSize = 30;
  23.    private int m_currentRecordCacheIndex = -1;
  24.    private int m_topRowCacheIndex = -1;
  25.    private int m_bofCacheIndex = -1;
  26.    private int m_eofCacheIndex = -1;
  27.    private Object m_currentBookmark = null;
  28.    private Recordset m_externalRecordset = null;
  29.    private Recordset m_internalRecordset = null;
  30.    private IDataConsumer m_dataConsumer = null;
  31.    private int m_recordCount = -1;
  32.    private boolean m_empty = false;
  33.    private Recordset m_deleteRecordset = null;
  34.    RecordsetEventHandler m_onWillChangeFieldHandler = null;
  35.    RecordsetEventHandler m_onFieldChangeCompleteHandler = null;
  36.    RecordsetEventHandler m_onWillChangeRecordHandler = null;
  37.    RecordsetEventHandler m_onWillMoveHandler = null;
  38.    RecordsetEventHandler m_onRecordChangeCompleteHandler = null;
  39.    RecordsetEventHandler m_onWillChangeRecordsetHandler = null;
  40.    RecordsetEventHandler m_onRecordsetChangeCompleteHandler = null;
  41.    RecordsetEventHandler m_onMoveCompleteHandler = null;
  42.    RecordsetEventHandler m_onEndOfRecordsetHandler = null;
  43.  
  44.    public void onWillChangeFieldHandler(Object sender, RecordsetEvent event) {
  45.       if (this.m_dataConsumer != null) {
  46.          this.m_dataConsumer.onWillChangeFieldHandler(sender, event);
  47.       }
  48.  
  49.    }
  50.  
  51.    public void onWillChangeRecordHandler(Object sender, RecordsetEvent event) {
  52.       this.unhookEvents(this.m_externalRecordset);
  53.       if (event.adReason == 2 && event.cRecords > 0) {
  54.          Debug.trace("onWillChangeRecordHandler " + event.toString());
  55.          Debug.trace(sender.getClass().getName());
  56.          Recordset affected = null;
  57.          if (sender == this) {
  58.             affected = this.m_deleteRecordset;
  59.             Debug.trace("count before clone: " + affected.getRecordCount());
  60.          } else {
  61.             affected = new Recordset(sender);
  62.          }
  63.  
  64.          Debug.trace("count: " + affected.getRecordCount());
  65.          if (this.m_dataConsumer != null) {
  66.             Debug.trace("hit1");
  67.             int asyncHwnd = this.m_dataConsumer.getAsyncPostHwnd();
  68.             if (asyncHwnd != 0) {
  69.                Debug.trace("hit2");
  70.                this.m_dataConsumer.setAsyncPostMessage(2476);
  71.                boolean currentDeleted = true;
  72.                affected.moveFirst();
  73.  
  74.                for(int i = 0; i < event.cRecords; ++i) {
  75.                   Debug.trace("compare:" + bookmarkToLong(affected.getBookmark()) + " =?= " + bookmarkToLong(this.m_currentBookmark));
  76.                   if (bookmarksEqual(affected.getBookmark(), this.m_currentBookmark)) {
  77.                      Debug.trace("hit3");
  78.                      currentDeleted = true;
  79.                      break;
  80.                   }
  81.  
  82.                   affected.moveNext();
  83.                }
  84.  
  85.                if (currentDeleted) {
  86.                   Debug.trace("sending delay action message");
  87.                   this.m_currentBookmark = null;
  88.                   Windows.PostMessage(asyncHwnd, 2476, 1, 0);
  89.                }
  90.             }
  91.          }
  92.       }
  93.  
  94.       if (this.m_dataConsumer != null) {
  95.          this.m_dataConsumer.onWillChangeRecordHandler(sender, event);
  96.       }
  97.  
  98.       this.hookEvents(this.m_externalRecordset);
  99.    }
  100.  
  101.    public int getPageSize() {
  102.       return this.m_pageSize;
  103.    }
  104.  
  105.    public void setPageSize(int pageSize) {
  106.       this.verifyValidCache();
  107.       if (this.m_empty) {
  108.          this.m_pageSize = pageSize;
  109.          this.m_cacheSize = pageSize * 3;
  110.          this.m_eofCacheIndex = -1;
  111.          this.m_bofCacheIndex = -1;
  112.          this.m_currentRecordCacheIndex = -1;
  113.          this.m_cacheStartRatio = -23.23F;
  114.          this.m_cacheRowRatioSize = -23.23F;
  115.       } else {
  116.          boolean updateRatio = false;
  117.          if (this.m_cacheStartRatio != -23.23F) {
  118.             updateRatio = true;
  119.          }
  120.  
  121.          Object[] newCache = new Object[pageSize * 3];
  122.          float topRow = -23.23F;
  123.          Object bookmark = this.getBookmarkFromDisplayIndex(0);
  124.          System.arraycopy(this.m_bookmarkCache, this.m_topRowCacheIndex, newCache, pageSize, Math.min(pageSize, this.m_pageSize));
  125.          if (updateRatio) {
  126.             topRow = this.getTopRowRatio();
  127.          }
  128.  
  129.          this.m_pageSize = pageSize;
  130.          this.m_cacheSize = pageSize * 3;
  131.          this.m_eofCacheIndex = -1;
  132.          this.m_bofCacheIndex = -1;
  133.          this.m_currentRecordCacheIndex = -1;
  134.          if (updateRatio) {
  135.             this.m_cacheStartRatio = -23.23F;
  136.             this.m_cacheRowRatioSize = -23.23F;
  137.          }
  138.  
  139.          this.m_bookmarkCache = newCache;
  140.          this.m_topRowCacheIndex = this.m_pageSize;
  141.          this.m_currentRecordCacheIndex = this.getCacheIndexFromBookmark(this.m_currentBookmark);
  142.          if (updateRatio) {
  143.             this.m_cacheRowRatioSize = 1.0F / (float)this.getTotalRowCount();
  144.             this.m_cacheStartRatio = topRow - (float)this.m_topRowCacheIndex * this.m_cacheRowRatioSize;
  145.          }
  146.  
  147.          this.verifyValidCache();
  148.       }
  149.    }
  150.  
  151.    public void scrollToBottom() {
  152.       if (!this.m_empty) {
  153.          if (!this.fireViewScrollEvent()) {
  154.             this.clearCache();
  155.             this.m_internalRecordset.moveLast();
  156.             this.m_bookmarkCache[this.m_pageSize + this.m_pageSize] = this.m_internalRecordset.getBookmark();
  157.             this.m_internalRecordset.move(-1 * this.m_pageSize, this.m_bookmarkCache[this.m_pageSize + this.m_pageSize]);
  158.             this.m_topRowCacheIndex = this.m_pageSize;
  159.             this.m_bookmarkCache[this.m_topRowCacheIndex] = this.m_internalRecordset.getBookmark();
  160.             if (this.m_dataConsumer != null) {
  161.                this.m_dataConsumer.onViewScrolled(false, 0);
  162.             }
  163.  
  164.             this.verifyValidCache();
  165.          }
  166.       }
  167.    }
  168.  
  169.    public boolean fireViewScrollEvent() {
  170.       CancelEvent cancel = new CancelEvent(false);
  171.       if (this.m_dataConsumer != null) {
  172.          this.m_dataConsumer.onWillViewScroll(this, cancel);
  173.       }
  174.  
  175.       return cancel.cancel;
  176.    }
  177.  
  178.    public int getDisplayIndexFromBookmark(Object bookmark) {
  179.       this.verifyValidCache();
  180.       if (this.m_empty) {
  181.          return -1;
  182.       } else {
  183.          if (this.m_topRowCacheIndex >= 0) {
  184.             for(int i = this.m_topRowCacheIndex; i < this.m_cacheSize; ++i) {
  185.                if (bookmarksEqual(bookmark, this.m_bookmarkCache[i])) {
  186.                   return i - this.m_topRowCacheIndex;
  187.                }
  188.  
  189.                if (i >= this.m_topRowCacheIndex + this.m_pageSize) {
  190.                   break;
  191.                }
  192.             }
  193.          }
  194.  
  195.          return -1;
  196.       }
  197.    }
  198.  
  199.    public float getTopRowRatio() {
  200.       if (this.m_empty) {
  201.          return 0.0F;
  202.       } else if (this.m_cacheStartRatio != -23.23F) {
  203.          int rowCount = this.getTotalRowCount();
  204.          this.m_cacheRowRatioSize = 1.0F / (float)rowCount;
  205.          this.m_internalRecordset.move(0, this.getBookmarkFromDisplayIndex(0));
  206.          int abs = this.m_internalRecordset.getAbsolutePosition();
  207.          float topRowRatio = (float)abs / (float)rowCount;
  208.          this.m_cacheStartRatio = topRowRatio - (float)this.m_topRowCacheIndex * this.m_cacheRowRatioSize;
  209.          return topRowRatio;
  210.       } else {
  211.          return this.m_cacheStartRatio + (float)this.m_topRowCacheIndex * this.m_cacheRowRatioSize;
  212.       }
  213.    }
  214.  
  215.    public int getTotalRowCount() {
  216.       if (this.m_recordCount == -1) {
  217.          this.m_recordCount = this.m_internalRecordset.getRecordCount();
  218.       }
  219.  
  220.       return this.m_recordCount;
  221.    }
  222.  
  223.    public boolean isBookmarksOrdered() {
  224.       return this.m_externalRecordset.getProperties().getItem(86).getBoolean();
  225.    }
  226.  
  227.    public static long bookmarkToLong(Object bookmark) {
  228.       try {
  229.          byte[] data = ((Variant)bookmark).toSafeArray().toByteArray();
  230.          long temp = 0L;
  231.          if (data.length > 8) {
  232.             throw new IllegalArgumentException("bookmark can't be packed into a long");
  233.          } else {
  234.             for(int i = 0; i < data.length; ++i) {
  235.                temp += (long)(data[i] << i * 8);
  236.             }
  237.  
  238.             return temp;
  239.          }
  240.       } catch (ClassCastException var6) {
  241.          try {
  242.             int data = ((Variant)bookmark).toInt();
  243.             return (long)data;
  244.          } catch (ClassCastException var5) {
  245.             throw new IllegalArgumentException("bookmark can't be packed into a long");
  246.          }
  247.       }
  248.    }
  249.  
  250.    public void onFieldChangeCompleteHandler(Object sender, RecordsetEvent event) {
  251.       if (this.m_dataConsumer != null) {
  252.          this.m_dataConsumer.onFieldChangeCompleteHandler(sender, event);
  253.       }
  254.  
  255.    }
  256.  
  257.    public void onRecordChangeCompleteHandler(Object sender, RecordsetEvent event) {
  258.       this.unhookEvents(this.m_externalRecordset);
  259.       if (event.adReason == 2) {
  260.          Debug.trace("onRecordChangeCompleteHandler for delete " + event.toString());
  261.          Debug.trace(sender.getClass().getName());
  262.          Recordset affected = null;
  263.          if (sender == this) {
  264.             affected = this.m_deleteRecordset;
  265.             Debug.trace("count before clone(delete): " + this.m_deleteRecordset.getRecordCount());
  266.             Debug.trace("count before clone(external): " + this.m_externalRecordset.getRecordCount());
  267.             Debug.trace("count before clone(internal): " + this.m_internalRecordset.getRecordCount());
  268.          } else {
  269.             affected = new Recordset(sender);
  270.          }
  271.  
  272.          Debug.trace("count: " + affected.getRecordCount());
  273.          boolean foundGoodFirst = false;
  274.          Object first = null;
  275.          int currentTest = 0;
  276.          Debug.trace("a1");
  277.  
  278.          while(!foundGoodFirst) {
  279.             Debug.trace("b1");
  280.  
  281.             try {
  282.                first = this.getDisplayRow(currentTest).getBookmark();
  283.             } catch (AdoException var10) {
  284.                first = null;
  285.             }
  286.  
  287.             Debug.trace("b2");
  288.             if (first != null) {
  289.                foundGoodFirst = true;
  290.  
  291.                try {
  292.                   this.m_internalRecordset.move(0, first);
  293.                } catch (AdoException var9) {
  294.                   foundGoodFirst = false;
  295.                }
  296.             } else {
  297.                foundGoodFirst = false;
  298.             }
  299.  
  300.             Debug.trace("b5");
  301.             if (!foundGoodFirst) {
  302.                ++currentTest;
  303.                if (currentTest > this.getPageRowCount()) {
  304.                   Debug.trace("b6");
  305.                   break;
  306.                }
  307.             }
  308.          }
  309.  
  310.          Debug.trace("a2");
  311.          Debug.trace("clearing cache");
  312.          this.clearCache();
  313.          if (foundGoodFirst) {
  314.             this.m_topRowCacheIndex = this.m_pageSize;
  315.             this.m_bookmarkCache[this.m_topRowCacheIndex] = first;
  316.          }
  317.  
  318.          this.verifyValidCache();
  319.          if (this.m_empty) {
  320.             Debug.trace("Cache blown!");
  321.          }
  322.  
  323.          if (this.m_dataConsumer != null && this.m_currentBookmark != null) {
  324.             Debug.trace("telling consumer to repaint");
  325.             this.m_dataConsumer.onViewScrolled(false, -1);
  326.          }
  327.       }
  328.  
  329.       if (this.m_dataConsumer != null) {
  330.          this.m_dataConsumer.onRecordChangeCompleteHandler(sender, event);
  331.       }
  332.  
  333.       this.hookEvents(this.m_externalRecordset);
  334.    }
  335.  
  336.    public DataRow getCurrentRow() {
  337.       this.verifyValidCache();
  338.       if (this.m_empty) {
  339.          return null;
  340.       } else if (this.m_currentRecordCacheIndex == -1) {
  341.          return new DataRow(-1, this.m_currentBookmark);
  342.       } else {
  343.          int displayIndex = this.m_currentRecordCacheIndex - this.m_topRowCacheIndex;
  344.          if (displayIndex < 0 || displayIndex >= this.m_pageSize) {
  345.             displayIndex = -1;
  346.          }
  347.  
  348.          Object bookmark = this.m_bookmarkCache[this.m_currentRecordCacheIndex];
  349.          if (bookmark == null) {
  350.             this.fillCacheIndex(this.m_currentRecordCacheIndex);
  351.             Object var10000 = this.m_bookmarkCache[this.m_currentRecordCacheIndex];
  352.          }
  353.  
  354.          return new DataRow(displayIndex, this.m_bookmarkCache[this.m_currentRecordCacheIndex]);
  355.       }
  356.    }
  357.  
  358.    public void setCurrentRow(Object bookmark) {
  359.       if (!this.m_empty) {
  360.          this.m_externalRecordset.move(0, bookmark);
  361.       }
  362.    }
  363.  
  364.    private void clearCache() {
  365.       for(int i = 0; i < this.m_cacheSize; ++i) {
  366.          this.m_bookmarkCache[i] = null;
  367.       }
  368.  
  369.       this.m_topRowCacheIndex = -1;
  370.       this.m_currentRecordCacheIndex = -1;
  371.       this.m_cacheStartRatio = -23.23F;
  372.       this.m_cacheRowRatioSize = -23.23F;
  373.       this.m_eofCacheIndex = -1;
  374.       this.m_bofCacheIndex = -1;
  375.    }
  376.  
  377.    public void moveFirst() {
  378.       this.m_externalRecordset.moveFirst();
  379.    }
  380.  
  381.    public void onMoveCompleteHandler(Object sender, RecordsetEvent event) {
  382.       boolean updateDisplay = true;
  383.       switch (event.adReason) {
  384.          case 1:
  385.          case 2:
  386.          case 3:
  387.          case 4:
  388.          case 5:
  389.          case 6:
  390.          case 7:
  391.          case 8:
  392.          case 9:
  393.          case 11:
  394.             updateDisplay = false;
  395.          case 10:
  396.       }
  397.  
  398.       if (updateDisplay) {
  399.          this.m_currentBookmark = this.m_externalRecordset.getBookmark();
  400.          this.m_currentRecordCacheIndex = this.getCacheIndexFromBookmark(this.m_currentBookmark);
  401.          if (this.m_currentRecordCacheIndex != -1 && this.m_currentRecordCacheIndex >= this.m_pageSize && this.m_currentRecordCacheIndex <= this.m_cacheSize - this.m_pageSize) {
  402.             if (this.m_dataConsumer != null) {
  403.                this.m_dataConsumer.onViewScrolled(true, -1);
  404.             }
  405.          } else {
  406.             this.scrollCurrentIntoView();
  407.          }
  408.       }
  409.  
  410.       if (this.m_dataConsumer != null) {
  411.          this.m_dataConsumer.onMoveCompleteHandler(sender, event);
  412.       }
  413.  
  414.    }
  415.  
  416.    private void hookEvents(Recordset rs) {
  417.       if (this.m_onWillChangeFieldHandler == null) {
  418.          this.m_onWillChangeFieldHandler = new RecordsetEventHandler(this, "onWillChangeFieldHandler");
  419.          rs.addWillChangeFieldHandler(this.m_onWillChangeFieldHandler);
  420.          if (this.m_onFieldChangeCompleteHandler == null) {
  421.             this.m_onFieldChangeCompleteHandler = new RecordsetEventHandler(this, "onFieldChangeCompleteHandler");
  422.          }
  423.  
  424.          rs.addFieldChangeCompleteHandler(this.m_onFieldChangeCompleteHandler);
  425.          if (this.m_onWillChangeRecordHandler == null) {
  426.             this.m_onWillChangeRecordHandler = new RecordsetEventHandler(this, "onWillChangeRecordHandler");
  427.          }
  428.  
  429.          rs.addWillChangeRecordHandler(this.m_onWillChangeRecordHandler);
  430.          if (this.m_onWillMoveHandler == null) {
  431.             this.m_onWillMoveHandler = new RecordsetEventHandler(this, "onWillMoveHandler");
  432.          }
  433.  
  434.          rs.addWillMoveHandler(this.m_onWillMoveHandler);
  435.          if (this.m_onRecordChangeCompleteHandler == null) {
  436.             this.m_onRecordChangeCompleteHandler = new RecordsetEventHandler(this, "onRecordChangeCompleteHandler");
  437.          }
  438.  
  439.          rs.addRecordChangeCompleteHandler(this.m_onRecordChangeCompleteHandler);
  440.          if (this.m_onWillChangeRecordsetHandler == null) {
  441.             this.m_onWillChangeRecordsetHandler = new RecordsetEventHandler(this, "onWillChangeRecordsetHandler");
  442.          }
  443.  
  444.          rs.addWillChangeRecordsetHandler(this.m_onWillChangeRecordsetHandler);
  445.          if (this.m_onRecordsetChangeCompleteHandler == null) {
  446.             this.m_onRecordsetChangeCompleteHandler = new RecordsetEventHandler(this, "onRecordsetChangeCompleteHandler");
  447.          }
  448.  
  449.          rs.addRecordsetChangeCompleteHandler(this.m_onRecordsetChangeCompleteHandler);
  450.          if (this.m_onMoveCompleteHandler == null) {
  451.             this.m_onMoveCompleteHandler = new RecordsetEventHandler(this, "onMoveCompleteHandler");
  452.          }
  453.  
  454.          rs.addMoveCompleteHandler(this.m_onMoveCompleteHandler);
  455.          if (this.m_onEndOfRecordsetHandler == null) {
  456.             this.m_onEndOfRecordsetHandler = new RecordsetEventHandler(this, "onEndOfRecordsetHandler");
  457.          }
  458.  
  459.          rs.addEndOfRecordsetHandler(this.m_onEndOfRecordsetHandler);
  460.       }
  461.    }
  462.  
  463.    public void onRecordsetChangeCompleteHandler(Object sender, RecordsetEvent event) {
  464.       if (this.m_dataConsumer != null) {
  465.          this.m_dataConsumer.onRecordsetChangeCompleteHandler(sender, event);
  466.       }
  467.  
  468.    }
  469.  
  470.    public void scrollToFirst() {
  471.       if (!this.m_empty) {
  472.          if (!this.fireViewScrollEvent()) {
  473.             this.clearCache();
  474.             this.m_internalRecordset.moveFirst();
  475.             this.m_topRowCacheIndex = this.m_pageSize;
  476.             this.m_bookmarkCache[this.m_topRowCacheIndex] = this.m_internalRecordset.getBookmark();
  477.             if (this.m_dataConsumer != null) {
  478.                this.m_dataConsumer.onViewScrolled(false, 0);
  479.             }
  480.  
  481.             this.verifyValidCache();
  482.          }
  483.       }
  484.    }
  485.  
  486.    public Object getBookmarkFromDisplayIndex(int displayIndex) {
  487.       if (this.m_empty) {
  488.          return null;
  489.       } else {
  490.          if (this.m_topRowCacheIndex == -1) {
  491.             this.scrollToFirst();
  492.          }
  493.  
  494.          int cacheIndex = this.m_topRowCacheIndex + displayIndex;
  495.          if (cacheIndex < this.m_cacheSize) {
  496.             if (this.m_bookmarkCache[cacheIndex] == null) {
  497.                this.fillCacheIndex(cacheIndex);
  498.             }
  499.  
  500.             return this.m_bookmarkCache[cacheIndex];
  501.          } else {
  502.             return null;
  503.          }
  504.       }
  505.    }
  506.  
  507.    public void scrollCurrentIntoView() {
  508.       if (!this.m_empty) {
  509.          Object current = this.m_currentBookmark;
  510.          int currentCacheIndex = this.m_currentRecordCacheIndex;
  511.          int currentDisplayIndex = -1;
  512.          if (currentCacheIndex == -1) {
  513.             currentCacheIndex = this.getCacheIndexFromBookmark(current);
  514.             this.m_currentRecordCacheIndex = currentCacheIndex;
  515.          }
  516.  
  517.          if (currentCacheIndex != -1 && this.m_topRowCacheIndex != -1) {
  518.             currentDisplayIndex = currentCacheIndex - this.m_topRowCacheIndex;
  519.             if (-1 < currentDisplayIndex && currentDisplayIndex < this.m_pageSize) {
  520.                return;
  521.             }
  522.          }
  523.  
  524.          if (!this.fireViewScrollEvent()) {
  525.             if (currentCacheIndex > 0 && currentCacheIndex < this.m_cacheSize - this.m_pageSize) {
  526.                int offset = -1;
  527.                if (currentCacheIndex < this.m_topRowCacheIndex) {
  528.                   offset = this.m_topRowCacheIndex - currentCacheIndex;
  529.                   this.m_topRowCacheIndex = currentCacheIndex;
  530.                } else {
  531.                   offset = this.m_topRowCacheIndex - (currentCacheIndex - (this.m_pageSize - 1));
  532.                   this.m_topRowCacheIndex = currentCacheIndex - (this.m_pageSize - 1);
  533.                }
  534.  
  535.                if (this.m_dataConsumer != null) {
  536.                   this.m_dataConsumer.onViewScrolled(true, offset);
  537.                }
  538.             } else {
  539.                this.clearCache();
  540.                this.m_topRowCacheIndex = this.m_pageSize;
  541.                if (currentCacheIndex > 0) {
  542.                   this.m_internalRecordset.move(-1 * (this.m_pageSize - 2), current);
  543.                } else {
  544.                   this.m_internalRecordset.move(0, current);
  545.                }
  546.  
  547.                this.m_bookmarkCache[this.m_topRowCacheIndex] = this.m_internalRecordset.getBookmark();
  548.                this.m_internalRecordset.move(-1 * (this.m_pageSize - 1), this.m_bookmarkCache[this.m_topRowCacheIndex]);
  549.                this.m_bookmarkCache[0] = this.m_internalRecordset.getBookmark();
  550.                if (this.m_dataConsumer != null) {
  551.                   this.m_dataConsumer.onViewScrolled(false, 0);
  552.                }
  553.             }
  554.  
  555.             this.verifyValidCache();
  556.          }
  557.       }
  558.    }
  559.  
  560.    public void move(DataRow row, int offset) {
  561.       this.m_externalRecordset.move(offset, row.getBookmark());
  562.    }
  563.  
  564.    public Field getReadField(String name) {
  565.       try {
  566.          return this.m_internalRecordset.getFields().getItem(name);
  567.       } catch (AdoException var3) {
  568.          return null;
  569.       }
  570.    }
  571.  
  572.    public void move(DataRow row) {
  573.       this.m_externalRecordset.move(0, row.getBookmark());
  574.    }
  575.  
  576.    public Object getBookmarkRelative(int offset, Object bookmark) {
  577.       if (this.m_empty) {
  578.          return null;
  579.       } else {
  580.          Object newBookmark = null;
  581.          if (bookmark != null) {
  582.             this.m_internalRecordset.move(offset, bookmark);
  583.  
  584.             try {
  585.                newBookmark = this.m_internalRecordset.getBookmark();
  586.             } catch (AdoException var5) {
  587.             }
  588.          }
  589.  
  590.          return newBookmark;
  591.       }
  592.    }
  593.  
  594.    public Field getReadField(int i) {
  595.       try {
  596.          return this.m_internalRecordset.getFields().getItem(i);
  597.       } catch (AdoException var3) {
  598.          return null;
  599.       }
  600.    }
  601.  
  602.    protected int getCacheIndexFromBookmark(Object bookmark) {
  603.       this.verifyValidCache();
  604.       if (this.m_empty) {
  605.          return -1;
  606.       } else {
  607.          for(int i = 0; i < this.m_cacheSize; ++i) {
  608.             Object compare = this.m_bookmarkCache[i];
  609.             if (compare == null) {
  610.                this.fillCacheIndex(i);
  611.                compare = this.m_bookmarkCache[i];
  612.             }
  613.  
  614.             if (bookmarksEqual(bookmark, compare)) {
  615.                return i;
  616.             }
  617.          }
  618.  
  619.          return -1;
  620.       }
  621.    }
  622.  
  623.    private void optimizeCache() {
  624.       if (!this.m_empty) {
  625.          boolean updateRatio = false;
  626.          float topRow = -23.23F;
  627.          if (this.m_cacheStartRatio != -23.23F) {
  628.             updateRatio = true;
  629.             topRow = this.getTopRowRatio();
  630.          }
  631.  
  632.          this.m_eofCacheIndex = -1;
  633.          this.m_bofCacheIndex = -1;
  634.          this.m_currentRecordCacheIndex = -1;
  635.          if (updateRatio) {
  636.             this.m_cacheStartRatio = -23.23F;
  637.             this.m_cacheRowRatioSize = -23.23F;
  638.          }
  639.  
  640.          int delta = this.m_pageSize - this.m_topRowCacheIndex;
  641.          if (delta < 0) {
  642.             for(int i = 0; i < this.m_cacheSize + delta; ++i) {
  643.                this.m_bookmarkCache[i] = this.m_bookmarkCache[i - delta];
  644.             }
  645.  
  646.             for(int i = this.m_cacheSize + delta; i < this.m_cacheSize; ++i) {
  647.                this.m_bookmarkCache[i] = null;
  648.             }
  649.          } else {
  650.             for(int i = this.m_cacheSize - 1; i >= delta; --i) {
  651.                this.m_bookmarkCache[i] = this.m_bookmarkCache[i - delta];
  652.             }
  653.  
  654.             for(int i = delta; i >= 0; --i) {
  655.                this.m_bookmarkCache[i] = null;
  656.             }
  657.          }
  658.  
  659.          this.m_topRowCacheIndex = this.m_pageSize;
  660.          if (updateRatio) {
  661.             this.m_cacheRowRatioSize = 1.0F / (float)this.getTotalRowCount();
  662.             this.m_cacheStartRatio = topRow - (float)this.m_topRowCacheIndex * this.m_cacheRowRatioSize;
  663.          }
  664.  
  665.          this.m_currentRecordCacheIndex = this.getCacheIndexFromBookmark(this.m_currentBookmark);
  666.       }
  667.    }
  668.  
  669.    public boolean isBookmarksLiteral() {
  670.       return this.m_externalRecordset.getProperties().getItem(67).getBoolean();
  671.    }
  672.  
  673.    public static boolean rowsEqual(DataRow left, DataRow right) {
  674.       return left != null && right != null ? bookmarksEqual(left.getBookmark(), right.getBookmark()) : false;
  675.    }
  676.  
  677.    public DataProvider(Recordset external) {
  678.       if (external == null) {
  679.          throw new IllegalArgumentException("external can not be null");
  680.       } else {
  681.          this.m_externalRecordset = external;
  682.          this.m_internalRecordset = (Recordset)this.m_externalRecordset.clone();
  683.          this.m_currentBookmark = this.m_externalRecordset.getBookmark();
  684.          this.m_topRowCacheIndex = this.m_pageSize;
  685.          this.m_bookmarkCache[this.m_topRowCacheIndex] = this.m_currentBookmark;
  686.          this.m_currentRecordCacheIndex = this.getCacheIndexFromBookmark(this.m_currentBookmark);
  687.          this.hookEvents(this.m_externalRecordset);
  688.       }
  689.    }
  690.  
  691.    public void asyncMessageRecieved(Message msg) {
  692.       if (msg.msg == 2476) {
  693.          switch (msg.wParam) {
  694.             case 1:
  695.                Debug.trace("recieved delay action message");
  696.                boolean needRepaint = this.m_currentBookmark == null;
  697.  
  698.                try {
  699.                   this.m_externalRecordset.moveNext();
  700.                } catch (AdoException var4) {
  701.                   this.m_externalRecordset.moveLast();
  702.                }
  703.  
  704.                if (this.m_externalRecordset.getEOF()) {
  705.                   this.m_externalRecordset.moveLast();
  706.                }
  707.  
  708.                if (needRepaint && this.m_dataConsumer != null) {
  709.                   Debug.trace("forcing a repaint");
  710.                   this.m_dataConsumer.onViewScrolled(false, -1);
  711.                }
  712.          }
  713.       }
  714.  
  715.    }
  716.  
  717.    public int getColumnCount() {
  718.       return this.m_externalRecordset.getFields().getCount();
  719.    }
  720.  
  721.    public int getPageRowCount() {
  722.       if (this.m_empty) {
  723.          return 0;
  724.       } else if (this.m_eofCacheIndex != -1) {
  725.          return this.m_topRowCacheIndex + this.m_pageSize > this.m_eofCacheIndex ? this.m_eofCacheIndex - this.m_topRowCacheIndex : this.m_pageSize;
  726.       } else {
  727.          for(int i = this.m_topRowCacheIndex + this.m_pageSize - 1; i >= this.m_topRowCacheIndex; --i) {
  728.             Object current = this.m_bookmarkCache[i];
  729.             if (current == null) {
  730.                this.fillCacheIndex(i);
  731.                current = this.m_bookmarkCache[i];
  732.             }
  733.  
  734.             if (current != null) {
  735.                return i - this.m_topRowCacheIndex;
  736.             }
  737.  
  738.             if (this.m_eofCacheIndex >= 0) {
  739.                return this.getPageRowCount();
  740.             }
  741.          }
  742.  
  743.          throw new RuntimeException("Failed to calculate pagerowcount");
  744.       }
  745.    }
  746.  
  747.    public Field getWriteField(int i) {
  748.       try {
  749.          return this.m_externalRecordset.getFields().getItem(i);
  750.       } catch (AdoException var3) {
  751.          return null;
  752.       }
  753.    }
  754.  
  755.    public Field getWriteField(String name) {
  756.       try {
  757.          return this.m_externalRecordset.getFields().getItem(name);
  758.       } catch (AdoException var3) {
  759.          return null;
  760.       }
  761.    }
  762.  
  763.    public void onEndOfRecordsetHandler(Object sender, RecordsetEvent event) {
  764.       if (this.m_dataConsumer != null) {
  765.          this.m_dataConsumer.onEndOfRecordsetHandler(sender, event);
  766.       }
  767.  
  768.    }
  769.  
  770.    public void onWillChangeRecordsetHandler(Object sender, RecordsetEvent event) {
  771.       if (this.m_dataConsumer != null) {
  772.          this.m_dataConsumer.onWillChangeRecordsetHandler(sender, event);
  773.       }
  774.  
  775.    }
  776.  
  777.    public String getFormattedData(DataRow row, Field field) {
  778.       if (this.m_empty) {
  779.          return null;
  780.       } else {
  781.          this.m_internalRecordset.move(0, row.getBookmark());
  782.          String data = field.getString();
  783.          return data == null ? "(null)" : data;
  784.       }
  785.    }
  786.  
  787.    public void onWillMoveHandler(Object sender, RecordsetEvent event) {
  788.       if (this.m_dataConsumer != null) {
  789.          this.m_dataConsumer.onWillMoveHandler(sender, event);
  790.       }
  791.  
  792.    }
  793.  
  794.    public void scroll(float ratio) {
  795.       if (!this.m_empty) {
  796.          if (!this.fireViewScrollEvent()) {
  797.             if ((double)ratio == (double)0.0F) {
  798.                this.scrollToFirst();
  799.             } else if ((double)ratio == (double)1.0F) {
  800.                this.scrollToBottom();
  801.             } else {
  802.                int rowCount = this.getTotalRowCount();
  803.                this.clearCache();
  804.                this.m_cacheRowRatioSize = 1.0F / (float)rowCount;
  805.                this.m_topRowCacheIndex = this.m_pageSize;
  806.                this.m_internalRecordset.setAbsolutePosition((int)(ratio * (float)rowCount));
  807.                this.m_bookmarkCache[this.m_topRowCacheIndex] = this.m_internalRecordset.getBookmark();
  808.                this.m_cacheStartRatio = ratio - (float)this.m_topRowCacheIndex * this.m_cacheRowRatioSize;
  809.                if (this.m_dataConsumer != null) {
  810.                   this.m_dataConsumer.onViewScrolled(false, 0);
  811.                }
  812.             }
  813.  
  814.             this.verifyValidCache();
  815.          }
  816.       }
  817.    }
  818.  
  819.    public void scroll(int offset, Object bookmark) {
  820.       if (!this.m_empty) {
  821.          Object newTopRow = null;
  822.  
  823.          try {
  824.             newTopRow = this.getBookmarkRelative(offset, bookmark);
  825.          } catch (Exception var11) {
  826.          }
  827.  
  828.          if (newTopRow != null) {
  829.             if (!this.fireViewScrollEvent()) {
  830.                int displayIndexOfBase = this.getDisplayIndexFromBookmark(bookmark);
  831.                int cacheIndexOfBase = -1;
  832.                if (displayIndexOfBase != -1) {
  833.                   cacheIndexOfBase = displayIndexOfBase + this.m_topRowCacheIndex;
  834.                }
  835.  
  836.                int cacheIndexOfDest = 0;
  837.                if (cacheIndexOfBase > 0) {
  838.                   cacheIndexOfDest = cacheIndexOfBase + offset;
  839.                }
  840.  
  841.                if (cacheIndexOfBase > 0 && cacheIndexOfDest > 0 && cacheIndexOfDest < this.m_cacheSize - this.m_pageSize) {
  842.                   int topRowOffset = this.m_topRowCacheIndex - cacheIndexOfDest;
  843.                   this.m_topRowCacheIndex = cacheIndexOfDest;
  844.                   if (this.m_dataConsumer != null) {
  845.                      this.m_dataConsumer.onViewScrolled(true, topRowOffset);
  846.                   }
  847.  
  848.                   this.optimizeCache();
  849.                } else {
  850.                   float currentRatio = -1.0F;
  851.                   if (displayIndexOfBase != -1) {
  852.                      currentRatio = this.m_cacheStartRatio;
  853.                   }
  854.  
  855.                   Object newTop = null;
  856.  
  857.                   try {
  858.                      this.m_internalRecordset.move(offset, bookmark);
  859.                      newTop = this.m_internalRecordset.getBookmark();
  860.                   } catch (AdoException var10) {
  861.                   }
  862.  
  863.                   if (newTop != null) {
  864.                      this.clearCache();
  865.                      this.m_topRowCacheIndex = this.m_pageSize;
  866.                      this.m_bookmarkCache[this.m_topRowCacheIndex] = newTop;
  867.                      if ((double)currentRatio >= (double)0.0F) {
  868.                      }
  869.  
  870.                      if (this.m_dataConsumer != null) {
  871.                         this.m_dataConsumer.onViewScrolled(false, 0);
  872.                      }
  873.                   } else if (offset > 0) {
  874.                      this.scrollToBottom();
  875.                   } else {
  876.                      this.scrollToFirst();
  877.                   }
  878.                }
  879.  
  880.                this.verifyValidCache();
  881.             }
  882.          }
  883.       }
  884.    }
  885.  
  886.    public void setFormattedData(Field field, String data) {
  887.       if (!this.m_empty) {
  888.          field.setString(data);
  889.       }
  890.    }
  891.  
  892.    public void moveLast() {
  893.       this.m_externalRecordset.moveLast();
  894.    }
  895.  
  896.    private void fillCacheIndex(int cacheIndex) {
  897.       if (!this.m_empty) {
  898.          int filledCacheIndex = -1;
  899.          boolean found = false;
  900.          Debug.assert(cacheIndex >= 0 && cacheIndex < this.m_cacheSize, "Invalid cacheIndex");
  901.          this.verifyValidCache();
  902.          if ((this.m_bofCacheIndex < 0 || cacheIndex > this.m_bofCacheIndex) && (this.m_eofCacheIndex < 0 || cacheIndex < this.m_eofCacheIndex)) {
  903.             for(int offset = 1; offset < this.m_cacheSize / 2; ++offset) {
  904.                filledCacheIndex = cacheIndex - offset;
  905.                if (filledCacheIndex > 0 && this.m_bookmarkCache[filledCacheIndex] != null) {
  906.                   found = true;
  907.                   break;
  908.                }
  909.  
  910.                filledCacheIndex = cacheIndex + offset;
  911.                if (filledCacheIndex < this.m_cacheSize && this.m_bookmarkCache[filledCacheIndex] != null) {
  912.                   found = true;
  913.                   break;
  914.                }
  915.             }
  916.  
  917.             if (!found) {
  918.                for(int i = 0; i < this.m_cacheSize; ++i) {
  919.                   if (this.m_bookmarkCache[i] != null) {
  920.                      filledCacheIndex = i;
  921.                      found = true;
  922.                      break;
  923.                   }
  924.                }
  925.             }
  926.  
  927.             if (!found) {
  928.                throw new IllegalArgumentException("Invalid cache state. This error should never be seen, only here for debug purposes.");
  929.             } else {
  930.                this.m_internalRecordset.move(cacheIndex - filledCacheIndex, this.m_bookmarkCache[filledCacheIndex]);
  931.                if (this.m_internalRecordset.getBOF()) {
  932.                   this.m_internalRecordset.move(0, this.m_bookmarkCache[filledCacheIndex]);
  933.                   int bofCacheIndex = filledCacheIndex;
  934.  
  935.                   while(!this.m_internalRecordset.getBOF()) {
  936.                      this.m_internalRecordset.movePrevious();
  937.                      --bofCacheIndex;
  938.                      if (!this.m_internalRecordset.getBOF()) {
  939.                         this.m_bookmarkCache[bofCacheIndex] = this.m_internalRecordset.getBookmark();
  940.                      }
  941.                   }
  942.  
  943.                   this.m_bofCacheIndex = bofCacheIndex;
  944.                   this.m_internalRecordset.move(0, this.m_bookmarkCache[filledCacheIndex]);
  945.                } else if (this.m_internalRecordset.getEOF()) {
  946.                   this.m_internalRecordset.move(0, this.m_bookmarkCache[filledCacheIndex]);
  947.                   int eofCacheIndex = filledCacheIndex;
  948.  
  949.                   while(!this.m_internalRecordset.getEOF()) {
  950.                      this.m_internalRecordset.moveNext();
  951.                      ++eofCacheIndex;
  952.                      if (!this.m_internalRecordset.getEOF()) {
  953.                         this.m_bookmarkCache[eofCacheIndex] = this.m_internalRecordset.getBookmark();
  954.                      }
  955.                   }
  956.  
  957.                   this.m_eofCacheIndex = eofCacheIndex;
  958.                   this.m_internalRecordset.move(0, this.m_bookmarkCache[filledCacheIndex]);
  959.                } else {
  960.                   this.m_bookmarkCache[cacheIndex] = this.m_internalRecordset.getBookmark();
  961.                }
  962.  
  963.             }
  964.          }
  965.       }
  966.    }
  967.  
  968.    public int getLastDisplayIndex() {
  969.       this.verifyValidCache();
  970.       if (this.m_empty) {
  971.          return -1;
  972.       } else {
  973.          if (this.m_eofCacheIndex >= 0) {
  974.             if (this.m_eofCacheIndex < this.m_topRowCacheIndex + this.m_pageSize) {
  975.                return this.m_eofCacheIndex - this.m_topRowCacheIndex;
  976.             }
  977.          } else {
  978.             for(int i = this.m_topRowCacheIndex + this.m_pageSize - 1; i >= this.m_topRowCacheIndex && this.m_bookmarkCache[i] == null; --i) {
  979.                this.fillCacheIndex(i);
  980.                if (this.m_eofCacheIndex >= 0) {
  981.                   return this.getLastDisplayIndex();
  982.                }
  983.             }
  984.          }
  985.  
  986.          return -1;
  987.       }
  988.    }
  989.  
  990.    public void deleteRows(DataRow[] rows) {
  991.       if (!this.m_empty) {
  992.          if (rows != null) {
  993.             this.m_deleteRecordset = (Recordset)this.m_externalRecordset.clone();
  994.             Variant[] bookmarksList = new Variant[rows.length];
  995.  
  996.             for(int i = 0; i < rows.length; ++i) {
  997.                bookmarksList[i] = (Variant)rows[i].getBookmark();
  998.             }
  999.  
  1000.             Variant bookmarks = new Variant();
  1001.             bookmarks.putVariantArray(bookmarksList);
  1002.             Object oldFilter = this.m_deleteRecordset.getFilter();
  1003.             Debug.trace("setting filter to bookmarks");
  1004.             this.m_deleteRecordset.setFilter(bookmarks);
  1005.             Debug.trace("deleting group");
  1006.             this.m_deleteRecordset.delete(2);
  1007.             this.m_deleteRecordset = null;
  1008.          }
  1009.       }
  1010.    }
  1011.  
  1012.    public void moveNext() {
  1013.       this.m_externalRecordset.moveNext();
  1014.    }
  1015.  
  1016.    public void setDataConsumer(IDataConsumer consumer) {
  1017.       this.m_dataConsumer = consumer;
  1018.    }
  1019.  
  1020.    private void unhookEvents(Recordset rs) {
  1021.       rs.removeWillChangeFieldHandler(this.m_onWillChangeFieldHandler);
  1022.       rs.removeFieldChangeCompleteHandler(this.m_onFieldChangeCompleteHandler);
  1023.       rs.removeWillChangeRecordHandler(this.m_onWillChangeRecordHandler);
  1024.       rs.removeWillMoveHandler(this.m_onWillMoveHandler);
  1025.       rs.removeRecordChangeCompleteHandler(this.m_onRecordChangeCompleteHandler);
  1026.       rs.removeWillChangeRecordsetHandler(this.m_onWillChangeRecordsetHandler);
  1027.       rs.removeRecordsetChangeCompleteHandler(this.m_onRecordsetChangeCompleteHandler);
  1028.       rs.removeMoveCompleteHandler(this.m_onMoveCompleteHandler);
  1029.       rs.removeEndOfRecordsetHandler(this.m_onEndOfRecordsetHandler);
  1030.    }
  1031.  
  1032.    public void movePrevious() {
  1033.       this.m_externalRecordset.movePrevious();
  1034.    }
  1035.  
  1036.    private void verifyValidCache() {
  1037.       for(int i = 0; i < this.m_cacheSize; ++i) {
  1038.          if (this.m_bookmarkCache[i] != null) {
  1039.             return;
  1040.          }
  1041.       }
  1042.  
  1043.       if (!this.m_empty) {
  1044.          Debug.trace("Cache State is becoming 'Empty'");
  1045.          Throwable t = new Throwable();
  1046.          t.printStackTrace();
  1047.       }
  1048.  
  1049.       this.m_empty = true;
  1050.       Debug.trace("Cache State is 'Empty'");
  1051.    }
  1052.  
  1053.    public DataRow getDisplayRow(Object bookmark) {
  1054.       this.verifyValidCache();
  1055.       return this.m_empty ? null : new DataRow(this.getDisplayIndexFromBookmark(bookmark), bookmark);
  1056.    }
  1057.  
  1058.    public DataRow getDisplayRow(int displayIndex) {
  1059.       this.verifyValidCache();
  1060.       if (this.m_empty) {
  1061.          return null;
  1062.       } else {
  1063.          Object bookmark = this.getBookmarkFromDisplayIndex(displayIndex);
  1064.          return bookmark != null ? new DataRow(displayIndex, bookmark) : null;
  1065.       }
  1066.    }
  1067.  
  1068.    public void refresh() {
  1069.       DataRow top = this.getDisplayRow(0);
  1070.       Object bookmarkTop = null;
  1071.       if (top != null) {
  1072.          bookmarkTop = top.getBookmark();
  1073.       }
  1074.  
  1075.       this.clearCache();
  1076.       this.m_topRowCacheIndex = this.m_pageSize;
  1077.       if (bookmarkTop == null) {
  1078.          try {
  1079.             this.m_internalRecordset.moveFirst();
  1080.             bookmarkTop = this.m_internalRecordset.getBookmark();
  1081.          } catch (AdoException var4) {
  1082.             bookmarkTop = null;
  1083.          }
  1084.       }
  1085.  
  1086.       this.m_bookmarkCache[this.m_topRowCacheIndex] = bookmarkTop;
  1087.       this.m_recordCount = -1;
  1088.       this.verifyValidCache();
  1089.    }
  1090.  
  1091.    public static boolean bookmarksEqual(Object left, Object right) {
  1092.       boolean match = true;
  1093.       if (left != null && right != null) {
  1094.          try {
  1095.             byte[] leftData = ((Variant)left).toSafeArray().toByteArray();
  1096.             byte[] rightData = ((Variant)right).toSafeArray().toByteArray();
  1097.             if (leftData.length == rightData.length) {
  1098.                for(int i = 0; i < leftData.length; ++i) {
  1099.                   if (leftData[i] != rightData[i]) {
  1100.                      match = false;
  1101.                      break;
  1102.                   }
  1103.                }
  1104.             } else {
  1105.                match = false;
  1106.             }
  1107.          } catch (ClassCastException var7) {
  1108.             try {
  1109.                int leftData = ((Variant)left).toInt();
  1110.                int rightData = ((Variant)right).toInt();
  1111.                if (leftData != rightData) {
  1112.                   match = false;
  1113.                }
  1114.             } catch (ClassCastException var6) {
  1115.                match = false;
  1116.             }
  1117.          }
  1118.       } else {
  1119.          match = false;
  1120.       }
  1121.  
  1122.       return match;
  1123.    }
  1124. }
  1125.